package com.wl.lib.dialog

import android.annotation.SuppressLint
import android.annotation.TargetApi
import android.app.Dialog
import android.content.Context
import android.content.DialogInterface
import android.os.Build
import android.os.Build.VERSION_CODES.KITKAT
import android.text.Layout
import android.util.TypedValue
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.WindowManager
import android.widget.TextView
import androidx.core.view.isVisible
import com.wl.lib.base.R
import com.wl.lib.extension.dp
import com.wl.lib.utils.ResUtils
import com.wl.lib.utils.StatusBarUtils

// Created by wangliang on 2024/12/6

private typealias ConfirmAction = ((DialogInterface) -> Unit)?

private typealias DismissAction = ((DialogInterface) -> Unit)?

class ConfirmDialogBuilder {

    private val dialog: Dialog
    private val contentView: View

    private val titleView: TextView?
    private val titleDescDivider: View?
    private val contentContainer: ViewGroup?
    private var descView: TextView?
    private val positiveButton: TextView?
    private val negativeButton: TextView?
    private val buttonDivider: View?
    private var isDescriptionSetup: Boolean = false
    private var isContentViewSetup: Boolean = false

    @JvmOverloads
    constructor (
        context: Context,
        customLayoutId: Int = R.layout.view_common_confirm_dialog,
        style: Int = android.R.style.Theme_Translucent_NoTitleBar
    ) : this(Dialog(context, style), LayoutInflater.from(context).inflate(customLayoutId, null))

    @JvmOverloads
    constructor (
        customDialog: Dialog, customLayoutId: Int = R.layout.view_common_confirm_dialog
    ) : this(customDialog, LayoutInflater.from(customDialog.context).inflate(customLayoutId, null))

    private constructor(dialog: Dialog, contentView: View) {
        this.dialog = dialog
        this.contentView = contentView
        dialog.setContentView(this.contentView)

        titleView = contentView.findViewById(R.id.confirm_dialog_title) as? TextView
        titleDescDivider = contentView.findViewById(R.id.confirm_dialog_title_desc_divider)
        contentContainer = contentView.findViewById(R.id.content_container) as? ViewGroup
        descView = contentView.findViewById(R.id.confirm_dialog_description) as? TextView
        positiveButton = contentView.findViewById(R.id.confirm_button_positive) as? TextView
        negativeButton = contentView.findViewById(R.id.confirm_button_negative) as? TextView
        buttonDivider = contentView.findViewById(R.id.confirm_button_divider_middle)

        titleView?.visibility = View.GONE
        titleDescDivider?.visibility = View.GONE
        contentContainer?.visibility = View.GONE
        descView?.visibility = View.GONE
        positiveButton?.visibility = View.GONE
        negativeButton?.visibility = View.GONE
        buttonDivider?.visibility = View.GONE

        setCancelable(false)
    }

    @JvmOverloads
    fun setTitle(title: CharSequence?, gravity: Int = Gravity.CENTER): ConfirmDialogBuilder {
        titleView?.let {
            if (title.isNullOrBlank()) {
                it.visibility = View.GONE
            } else {
                it.visibility = View.VISIBLE
                it.text = title
                it.gravity = gravity
            }
        }
        return this
    }

    @SuppressLint("WrongConstant")
    @TargetApi(Build.VERSION_CODES.M)
    @JvmOverloads
    fun setDescription(
        description: CharSequence?,
        gravity: Int = Gravity.CENTER,
        breakStrategy: Int = Layout.BREAK_STRATEGY_HIGH_QUALITY
    ): ConfirmDialogBuilder {
        descView?.let {
            if (description.isNullOrBlank()) {
                it.visibility = View.GONE
                contentContainer?.visibility = View.GONE
            } else {
                it.visibility = View.VISIBLE
                contentContainer?.visibility = View.VISIBLE
                it.text = description
                it.gravity = gravity
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    it.breakStrategy = breakStrategy
                }
            }
        }
        isDescriptionSetup = true
        return this
    }

    fun setContentView(contentView: View): ConfirmDialogBuilder {
        contentContainer?.let {
            it.removeAllViews()
            descView = null
            it.addView(contentView)
            it.isVisible = true
        }
        isContentViewSetup = true
        return this
    }

    @JvmOverloads
    fun setPositiveAction(
        positiveHint: CharSequence? = ResUtils.getString(R.string.confirm_dialog_ok),
        emphasize: Boolean = false,
        positiveAction: ConfirmAction = { it.dismiss() }
    ): ConfirmDialogBuilder {
        setConfirmButton(positiveButton, positiveHint, positiveAction, dialog, emphasize)
        return this
    }

    @JvmOverloads
    fun setPositiveAction(
        positiveAction: ConfirmAction,
        positiveHint: CharSequence? = ResUtils.getString(R.string.confirm_dialog_ok),
        emphasize: Boolean = false
    ): ConfirmDialogBuilder {
        setConfirmButton(positiveButton, positiveHint, positiveAction, dialog, emphasize)
        return this
    }

    @JvmOverloads
    fun setNegativeAction(
        negativeHint: CharSequence? = ResUtils.getString(R.string.confirm_dialog_cancel),
        emphasize: Boolean = false,
        negativeAction: ConfirmAction = { it.dismiss() }
    ): ConfirmDialogBuilder {
        setConfirmButton(negativeButton, negativeHint, negativeAction, dialog, emphasize)
        return this
    }

    @JvmOverloads
    fun setNegativeAction(
        negativeAction: ConfirmAction,
        negativeHint: CharSequence? = ResUtils.getString(R.string.confirm_dialog_cancel),
        emphasize: Boolean = false
    ): ConfirmDialogBuilder {
        setConfirmButton(negativeButton, negativeHint, negativeAction, dialog, emphasize)
        return this
    }

    private fun setConfirmButton(
        button: TextView?, hint: CharSequence?, action: ConfirmAction, dialog: DialogInterface, emphasize: Boolean
    ) {
        button?.let {
            if (hint.isNullOrBlank()) {
                it.visibility = View.GONE
                it.setOnClickListener(null)
            } else {
                it.visibility = View.VISIBLE
                it.paint.isFakeBoldText = emphasize
                it.text = hint
                it.setOnClickListener { action?.invoke(dialog) }
            }
        }
    }

    fun setDismissAction(
        dismissAction: DismissAction?
    ): ConfirmDialogBuilder {
        dialog.setOnDismissListener { dismissAction?.invoke(dialog) }
        return this
    }

    @JvmOverloads
    fun setCancelable(
        cancelable: Boolean, onCancelListener: DialogInterface.OnCancelListener = DialogInterface.OnCancelListener {}
    ): ConfirmDialogBuilder {
        dialog.setCancelable(cancelable)
        dialog.setCanceledOnTouchOutside(cancelable)
        dialog.setOnCancelListener(onCancelListener)
        if (!cancelable) {
            contentView.setOnClickListener(null)
        } else {
            contentView.setOnClickListener {
                if (cancelable) {
                    onCancelListener.onCancel(dialog)
                    dialog.dismiss()
                }
            }
        }
        return this
    }

    fun build(): Dialog {
        validate()
        checkContentViewStyle()
        checkConfirmButtonStyle()
        StatusBarUtils.setLightTransparentStatusBar(dialog.window)
        return dialog
    }

    fun buildAndShow() = build().show()

    fun buildAndShowImmersiveMode() = build().showWithImmersiveMode()

    private fun validate() {
        if ((titleView == null || titleView.visibility != View.VISIBLE) && (descView == null || descView?.visibility != View.VISIBLE) && (contentContainer == null || contentContainer.visibility != View.VISIBLE)) {
            throw IllegalStateException(
                "Title and description are both empty, or titleView and descriptionView are not found."
            )
        }
        if ((positiveButton == null || positiveButton.visibility != View.VISIBLE) && (negativeButton == null || negativeButton.visibility != View.VISIBLE)) {
            throw IllegalStateException(
                "Positive and negative hints are both empty, or positiveButton and negativeButton are not found."
            )
        }
        if (isContentViewSetup && isDescriptionSetup) {
            throw IllegalStateException(
                "Contentview and description are both set to show, one of them will be covered."
            )
        }
    }

    private fun checkContentViewStyle() {
        if (descView?.visibility == View.VISIBLE) {
            descView?.let {
                if (titleView?.visibility == View.VISIBLE) {
                    titleDescDivider?.visibility = View.VISIBLE
                    it.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 13f)
                    it.setTextColor(ResUtils.getColor(R.color.color_002))
                    it.setLineSpacing(5.dp.toFloat(), 1f)
                } else {
                    titleDescDivider?.visibility = View.GONE
                    it.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15f)
                    it.setTextColor(ResUtils.getColor(R.color.color_001))
                    it.setLineSpacing(8.dp.toFloat(), 1f)
                }
            }
        } else {
            titleDescDivider?.visibility = View.GONE
        }
    }

    private fun checkConfirmButtonStyle() {
        if (positiveButton == null || positiveButton.visibility != View.VISIBLE) {
            negativeButton?.setBackgroundResource(R.drawable.selector_dialog_single_button)
            buttonDivider?.visibility = View.GONE
        } else if (negativeButton == null || negativeButton.visibility != View.VISIBLE) {
            positiveButton.setBackgroundResource(R.drawable.selector_dialog_single_button)
            buttonDivider?.visibility = View.GONE
        } else {
            positiveButton.setBackgroundResource(R.drawable.selector_dialog_common_button_left)
            negativeButton.setBackgroundResource(R.drawable.selector_dialog_common_button_right)
            buttonDivider?.visibility = View.VISIBLE
        }
    }
}

fun Dialog.showWithImmersiveMode() {
    // 处理弹出时底部导航栏会显示的问题
    window?.setFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE)
    if (window?.decorView != null) {
        if (Build.VERSION.SDK_INT >= KITKAT) {
            val systemUI = (View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                    or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                    or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                    or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION // hide nav bar
                    or View.SYSTEM_UI_FLAG_FULLSCREEN // hide status bar
                    or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY)

            window?.decorView?.systemUiVisibility = systemUI
        }
    }
    this.show()
    window?.clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE)
}

